use rand::Rng;
use regex::Regex;
use std::borrow::{Borrow, BorrowMut};
use std::fs::{File, OpenOptions};
use std::io::{BufWriter, Write};
use std::net::TcpStream;
use std::str::FromStr;

#[derive(Debug)]
struct MyWriter<W> {
    writer: W,
}

impl MyWriter<BufWriter<TcpStream>> {
    pub fn new(addr: &str) -> MyWriter<BufWriter<TcpStream>> {
        let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
        Self {
            writer: BufWriter::new(stream),
        }
    }

    pub fn write(&mut self, buf: &str) -> std::io::Result<()> {
        self.writer.write_all(buf.as_bytes())
    }
}

impl<W: Write> MyWriter<W> {
    pub fn new2(writer: W) -> Self {
        Self { writer }
    }
}
impl MyWriter<File> {
    pub fn new3(addr: &str) -> Self {
        let file = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .append(true)
            .open(addr)
            .unwrap();
        Self { writer: file }
    }
}

#[test]
fn test_explict_impl() {
    let mut writer: MyWriter<BufWriter<TcpStream>> =
        MyWriter::<BufWriter<TcpStream>>::new("127.0.0.1:8080");
    writer.write("hello world!");
}
#[test]
fn test_implicit_impl() {
    let write = BufWriter::new(TcpStream::connect("127.0.0.1:8080").unwrap());
    let mut myWrite = MyWriter::new2(write);
    myWrite.write("abc dddd");
}
#[test]
fn test_write_local() {
    let mut myWrite = MyWriter::<File>::new3("/Users/apple/abc.txt");
    if let Ok(rst) = myWrite.writer.write("127.0.0.1 localhost".as_bytes()) {
        println!("rst:{:?}", rst)
    }
}
#[test]
fn test_matrix_not_good() {
    let mut data: Vec<*const u8> = Vec::new();

    for i in 0..5 {
        let mut num: Vec<u8> = Vec::new();
        for i in 0..16 {
            unsafe {
                let rand_num: u8 = rand::thread_rng().gen();
                num.push(rand_num)
            }
        }
        println!("num is : {:?},num.as_ptr(): {:?}", num, num.as_ptr());
        data.push(num.as_ptr());
    }
    println!("data is: {:?}", data);
    //后面的地址都是同一个！
    //data is: [0x7fa491604390, 0x7fa491604390, 0x7fa491604390, 0x7fa491604390, 0x7fa491604390]
}
#[test]
fn test_matrix_good() {
    let mut data: Vec<*const [u8]> = Vec::new();

    for _i in 0..5 {
        let mut num: Vec<u8> = Vec::new();
        for _j in 0..16 {
            let rand_num: u8 = rand::thread_rng().gen();
            num.push(rand_num);
        }
        println!("num({:p}) is : {:?}", &*num, num);
        let boxed = num.into_boxed_slice();
        data.push(Box::into_raw(boxed) as _);
    }
    println!("data is: {:?}", data);
}

pub trait Parse {
    fn parse(s: &str) -> Self;
}
// impl Parse for u8 {
//     fn parse(s: &str) -> u8 {
//         let re: Regex = Regex::new(r"^[0-9]+").unwrap();
//         if let Some(first) = re.captures(s) {
//             first.get(0).map_or(0, |s| s.as_str().parse().unwrap_or(0))
//         } else {
//             0
//         }
//     }
// }

impl<T> Parse for T
where
    T: FromStr + Default,
{
    fn parse(s: &str) -> Self {
        let re: Regex = Regex::new(r"^[0-9]+").unwrap();
        // 生成一个创建缺省值的闭包，这里主要是为了简化后续代码
        // Default::default() 返回的类型根据上下文能推导出来，是 Self
        // 而我们约定了 Self，也就是 T 需要实现 Default trait
        let d = || Default::default();
        if let Some(captures) = re.captures(s) {
            captures
                .get(0)
                .map_or(d(), |s| s.as_str().parse().unwrap_or(d()))
        } else {
            ///这里返回缺省值的话，会跟解析 “0abcd” 这样的情况混淆，不知道解析出的 0，究竟是出错了，还是本该解析出 0
            /// 更好的方式是 parse 函数返回一个 Result<T,E>
            d()
        }
    }
}

#[test]
fn parse_should_work() {
    assert_eq!(u8::parse("123abcd"), 123);
    assert_eq!(u8::parse("1234abcd"), 0);
    assert_eq!(u8::parse("abcd"), 0);
    println!("result: {}", u8::parse("255 hello world"));
}

#[test]
fn parse_should_work2() {
    assert_eq!(u32::parse("123abcd"), 123);
    assert_eq!(u32::parse("123.45abcd"), 123);
    assert_eq!(f64::parse("123.45abcd"), 123.0);
    assert_eq!(f64::parse("abcd"), 0f64);
}
